#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <wiringPi.h>
 
#define PORT    8888            
#define  LED  3		// LED Pin - wiringPi pin 3 is BCM_GPIO 22.(pyscial 15)
 
int get_temperature(float *temp);       /*该函数用于ds18b20采集温度*/

void blink_led() {
  for (int i=0;i < 3;i++)
  {
    digitalWrite(LED, HIGH) ;	// On
    delay(500) ;		        // mS
    digitalWrite(LED, LOW) ;	// Off
    delay(500) ;
  }

}

int alarm_signal = 0;
void handle_alarm_signal(int signum) {
    if (signum == SIGUSR1) {
        alarm_signal = 1;
    }
}

int main(int argc,char *argv[])
{
	
		if(wiringPiSetup() < 0){
		  printf("wiringPi setup failed.\n");
		  return 1;
		}

		pinMode(LED, OUTPUT);  // 设置输出模式
 
        int                     fd = -1;
        int                     rv = -1;
        struct sockaddr_in      servaddr;
        socklen_t               len = sizeof(servaddr);
        int                     r = -1;
        char                    t[16];
        float                   temp;
        char                    buf[128];
 
        fd = socket(AF_INET,SOCK_STREAM,0);
        if(fd < 0)
        {
                printf("create sockfd failure:%s\n",strerror(errno));
                return -1;
        }
        printf("create socket_fd [%d] successfully!\n",fd);
 
        memset(&servaddr,0,sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port   = htons(PORT);
        inet_aton(argv[1],&servaddr.sin_addr);
 
 
 
        if((rv = connect(fd,(struct sockaddr*)&servaddr,len)) < 0)
        {
                printf("client connect failure:%s\n",strerror(errno));
                return -2;
        }
                printf("client connect successfully!\n");
        
		pid_t pid = fork();  // 创建子进程
		if (pid < 0) {
			printf("failed to fork the child process\n");
			return -3;
		}
		
		else if (pid == 0) {  // 子进程负责闪烁LED
			signal(SIGUSR1, handle_alarm_signal);  // 注册信号处理函数
			while (1) 
			{
				pause(); // 等待接收到信号
				if (alarm_signal) {
                blink_led();
                alarm_signal = 0;
            }
			}
		} 
		
		else 
		{  // 父进程负责发送温度数据
			while(1)
			{
				if((r = get_temperature(&temp)) < 0)
				{
					printf("get temperature failure:%s\n",strerror(errno));
					return -7;
				}
				printf("get temperature successfully and temperature is %.2f!\n", temp);

				memset(t,0,sizeof(t));
				sprintf(t,"%.2f",temp);

				if((write(fd,t,sizeof(t))) < 0)
				{
					printf("write failure:%s\n",strerror(errno));
					return -8;
				}
				printf("write bytes:%s\n",t);

				if((rv = read(fd,buf,sizeof(buf))) <= 0)
				{
					printf("read failure or get disconnect:%s\n",strerror(errno));
					return -9;
				}
				printf("read [%d] bytes:%s\n",rv,buf);

				// 检查是否收到报警信号
				if (strcmp(buf, "Alarm") == 0)
				{
					printf("Received Alarm signal from server: Temperature exceeds threshold!\n");
					kill(pid, SIGUSR1); //向子进程发送信号
				}

				sleep(3);
			}
			close(fd);
		}
		return 0;
}
 
int get_temperature(float *temp)
{
 
        int             fd = -1;
        int             found = 0;
        char            w1_path[64] = "/sys/bus/w1/devices/";
        DIR             *dirp = NULL;
        struct dirent   *direntp = NULL;
        char            chip_sn[32];
        char            buf[128];
        char            *ptr;
 
        if( !(dirp = opendir(w1_path)) )
        {
                printf("open directory failure:%s\n",strerror(errno));
                return -3;
        }
 
        while( direntp = readdir(dirp) )
        {
 
                if( strstr(direntp->d_name,"28-") )
                {
                        strncpy(chip_sn,direntp->d_name,sizeof(chip_sn));
                        found = 1;      /*found用于确保是否能找到温度存储的文件*/
                }
        }
        if( !found )
        {
                printf("can not find ds18b20 directory!\n");
                return -4;
        }
 
        strncat(w1_path,chip_sn,sizeof(w1_path)-strlen(w1_path));               /*更新文件路径*/
        strncat(w1_path,"/w1_slave",sizeof(w1_path)-strlen(w1_path));
 
        closedir(dirp);
 
 
        fd = open(w1_path,O_RDONLY);    /*打开文件*/
        if(fd < 0)
        {
                printf("open file failure:%s\n",strerror(errno));
                return -5;
        }
 
 
        lseek(fd,0,SEEK_SET);           /*不设置文件偏移量可能造成读不到任何内容*/
        memset(buf,0,sizeof(buf));
        read(fd,buf,sizeof(buf));
 
        ptr = strstr(buf,"t="); /*找到t=字符串*/
        if(NULL == ptr)
        {
                printf("can not find t= string\n",strerror(errno));
                return -6;
        }
 
        ptr += 2;       /*将指针ptr移至t=后的温度值处*/
        *temp = atof(ptr)/1000;         /*进行温度转换和相应计算*/
 
        close(fd);
 
        return 0;
 
}